\documentstyle [a4,11pt,twoside]{article}
\textheight 240 mm
\textwidth 160mm
\topmargin -2.5cm
\evensidemargin -0.4cm
\oddsidemargin 1.0cm
\begin{document}

\thispagestyle{empty}
\begin {center}
\hskip2.1cm{\Large Институт физико-технических проблем}\\
\vskip1.6cm
\hskip9.8cm{\Large Дубна}
\end{center}
\hspace*{-10mm}\rule{170mm}{0.2mm}
\vskip1.0cm
\hskip11.5cm{\Large 93-10-8}\\
\vskip5.5cm
\hskip1.3cm{\Large O.S. Rasizade}
\vskip1.5cm
\begin{center}{\Large {\it Virtual Panels}: Graphics Interface
        for the Laboratory Instrumentation. 2.Objects}
\end{center}
\vskip9.0cm
\centerline{\Large 1993}

\newpage
\thispagestyle{empty}
\vspace*{6.0cm}
\hspace*{-6.5mm}{\bf \mbox{Rasizade O.S.}}\\
\vskip0.2cm
\hspace*{-6.5mm}{ {\bf {\it Virtual Panels}: Graphics Interface
        for the Laboratory Instrumentation. 2.Objects.}
\vskip0.5cm
\noindent
The complete description of Object classes of {\it Virtual Panels} -
object-oriented class library for creating data acquisition and
presentation applications with user-friendly interface is given.


\newpage

\small
\section*{4. Objects}

All generic features of Objects are inherited from the object base
class. These include title, size, type, status of the Object and all
chores of dragging, deleting, redrawing of Objects on the screen, all
necessary for this pointers and the memory management. The following
data members and methods are public in object class and are inherited
by all Objects.\\

 * Stack of Objects. This is the connected list of POPUP and on-the-
 screen PERM objects. Objects are pushed in this stack by
 {\it Virtual Panels} core
 when they are declared in the run-time order. Only PERM and POPUP
 Objects are pushed in the stack. The stack can be used only by the
 MASTER button system.\\

 * Active Object. You can rearrange the Stack of Objects and put the
 desired Object on the top of the stack calling the method MkActive()
 (look at the example 2.6.1 or example below). This makes the Object
 active. When the Object is active it can be manipulated from console
 while the program is in {\it Virtual Panels} Loop. The object can be
dragged, removed and so on.\\

 * Removing and Adding Objects. When the Object is removed (method
 Remove(), what means that the Object is cleared out from the screen) it
 remains in the stack if it is POPUP or removed from the stack if it is
 PERM. If the Object is not in the stack when MkActive() is called, it
 is pushed in the stack.\\

 * List of Objects. There is connected list of all Objects for internal
 use by {\it Virtual Panels} core. In this list Objects are added by their
 constructors and extracted by their destructors. The List of Objects
 is not connected with the button system.\\\\
{\large Data members:}\\

{\bf\raggedright
 int x0,y0,xmax,ymax;           {\sf // location of the Object}\\
 int xx0,yy0,xxmax,yymax;       {\sf // versatile location of the Object}
}

Size and location of the Object. May be used to determine the space taken
up by the Object on the screen (useful when you are disposing Objects on
the screen). These data members are read-only.\\

{\bf\raggedright
 unsigned OnScreen, Active;}

Read-only status data. If the Object is currently on the screen then
the status OnScreen is TRUE (non-zero), otherwise it is FALSE (zero).
The status Active is TRUE if the Object is active and is FALSE
otherwise. When the Object is active it is on the top of the Stack of
Objects. The status data have no sense for FIXED Objects.\\\\
{\large Methods:}\\

{\bf\raggedright
 virtual void Paint(void)=0;}

Paints the Object on the screen. This is a virtual method specific for
each Object.\\

{\bf\raggedright
 void GetXY(int *x0,int *y0,int *xmax,int *ymax);\\
 void GetXXYY(int *xx0,int *yy0,int *xxmax,int *yymax);}

These methods give you another way to get the location of the Object.
When there is an extensive use of the corresponding data members it is
more effective for size and speed of program to use the local variables
instead of the data members.\\

{\bf\raggedright
 void Remove(void);}

Removes POPUP or PERM Object from the screen and restores underlying
image. Also removes PERM Object from the Stack of Objects.\\

{\bf\raggedright
 void MkActive(void);}

Makes the Object active, what means that the Object is put on the top
of the Stack of Objects.  When the Object is active it can be
manipulated from console while program is in {\it Virtual Panels} Loop.
If the Object is not in the stack when MkActive() is called, it is pushed
in the stack.\\

{\bf\raggedright
 void MovetoXY(int x0,int y0);}

Changes the Objects location on the screen so, that its LEFT-TOP corner
will be at (x0,y0) (in VGA pixels). May be used to drag the Object
from the program. The following is the example of dragging of the
object SomeObject:

{\footnotesize\begin{verbatim}
SomeObject.Remove();    // remove Object from the current place
SomeObject.MovetoXY( newX0, newY0); // change location
SomeObject.Paint();     // paint it in the new location
SomeObject.MkActive();  // put it on the top of the stack
\end{verbatim}}

The following methods are static:\\

{\bf\raggedright
 void object::NextPERM(void);}

Makes active the next PERM Object in the Stack of Objects and repaints
it over other Objects on the screen. Usually this can be done from
console by striking F6 . This method allows you to do this from the
program.\\

{\bf\raggedright
 void object::RepaintScr(void);}

Repaints the Dragging area. Scans the Stack of Objects and paints only
PERM Objects with status OnScreen==TRUE, calling their paint
procedures. The Object closest to the top of the stack is painted last.
May be used to reclaim the Dragging area when it is corrupted.\\

{\raggedright
 {\bf int  object::SaveCnfg(char *cnffilename);}\\ \
\hspace{1cm}  returns:\\
\hspace{2cm}     0 if OK,\\
\hspace{2cm}    -1 if cannot write to or create configuration file\\
\hspace{2cm}    -2 if no PERM or POPUP objects currently exist}

Saves configuration of PERM and POPUP objects in cnffilename.\\

 {\raggedright
 {\bf int  object::LoadCnfg(char *cnffilename);}\\
\hspace{1cm}  returns:\\
\hspace{2cm}     0 if OK,\\
\hspace{2cm}    -1 if   cnffilename doesn't exist\\
\hspace{2cm}    -2 if   no PERM or POPUP objects currently exit\\
\hspace{2cm}    -3 if   keyword doesn't match}

Restores configuration of PERM and POPUP objects from cnffilename.

By configuration we mean locations and status data of objects and the
content of the Stack of Objects. Save the configuration before leaving
the program and then you can restore in the next session the last
changes you have made on the Dragging area.


\subsection*{4.1 Light-emitting diode (LED)}

Indeed the class LED is not the Object. It is a base class. Its only
destination is to show the light-emitting diode switched on or off
on the screen.\\\\
Constructors:\\

{\bf\raggedright
 LED(\\
\hspace{2cm}   int x0, int y0, {\sf  // position of the center of LED}\\
\hspace{2cm}   char *title,     {\sf // title of LED}\\
\hspace{6cm}           {\sf     // Hereafter are defaults}\\
\hspace{2cm}   int radius = 4,           {\sf // radius of indicator}\\
\hspace{2cm}   int txfont = 0,int txsize = 1,{\sf // font style and size of title}\\
\hspace{2cm}   LEDcolors color = redLED );   {\sf        // colors of LED}
}

This constructor must be used when you are declaring the LED indicator.
The title is always printed on the right side of indicator. There are
three pre-defined colors of LED: redLED, greenLED and yellowLED. In all
three color schemes the color of the title is black. But it can be changed
by customising colors ( see subsection Colors ).\\

{\bf\raggedright
 LED( int radius, LEDcolors color = redLED );}

This constructor can be used for special purposes, for example by
constructors of derived classes.\\\\
{\large Data members:}\\

{\bf\raggedright
 int on;}

Status of LED. Is TRUE ( nonzero ) if LED is lighted on then equal and
FALSE ( zero ) if LED is dark.\\\\
{\large Methods:}\\

{\bf\raggedright
 virtual void Paint(void);}

Paints LED indicator with title on the right side. Will be LED lighted
up or not depends on the value of data member on.\\

{\bf\raggedright
 void On(void);\\
 void Off(void);}

Switch the indicator on or off. Also sets or resets the data member on.\\

{\bf\raggedright
 void Invert(void)}

Changes the state of the LED indicator to the opposite.\\\\
{\large Color schemes:}\\

Color pattern for LED is provided by the structure\\

{\raggedright
 struct LEDcolors \{ COLORS\\
\hspace{4cm}                    title, // color of title\\
\hspace{4cm}                    on,    // lightened LED color\\
\hspace{4cm}                    off; \} // dark LED color}\\

There are three pre-defined color patterns for LED: redLED, greenLED and
yellowLED. They embrace all existing types of LED indicator and the only
color that may be reasonable to customize is the color of the title.

\subsection*{4.2 Indicator}

Indicator is the alpha-numeric one-row window where you can put data or
character strings. But there is a difference between Indicator and
a real window (such as an Outbox). When you declare Indicator you must
specify the format of the data output and this restricts you on what
you can put on Indicator. On the other hand this simplifies the
subsequent programming. In most of cases indicator is used to display
only one variable, e.g. temperature or voltage. It is reasonable to
attach this variable to Indicator. We defined Indicator as the
template class with one type parameter T - the type of the attached
variable.\\\\
Constructor:\\

{\bf\raggedright
 Indicator(\\
\hspace{2cm}    int x0,int y0,  {\sf // coord. of LEFT-TOP corner of Indicator}\\
\hspace{2cm}    objtype type,   {\sf // may be FIXED, PERM, POPUP}\\
\hspace{2cm}    char * title,   {\sf // title of Indicator}\\
\hspace{2cm}    int dispwidth,  {\sf // width of display in characters}\\
\hspace{2cm}    T *variable,    {\sf // pointer to variable attached to indicator}\\
\hspace{2cm}    char *format,   {\sf // format of indicated data}\\
\hspace{6cm}                    {\sf //---------- Hereafter are defaults}\\
\hspace{2cm}    int frame=UNFRAMED,{\sf         // display may FRAMED or UNFRAMED}\\
\hspace{4cm}            {\sf // proc supplied by programmer to repaint Indicator}\\
\hspace{2cm}    void (far *paintproc)()=procNULL,{\sf // only for PERM indicators}\\
\hspace{2cm}    int  datafont=0,int datafontsize=1, {\sf        // font of indicated data}\\
\hspace{2cm}    int  titlefont=0,int titlefontsize=1, {\sf      // font of title}\\
\hspace{2cm}    plaquecolors indframecolcnfg=plaquecoldflt,{\sf // colors of frame}\\
\hspace{2cm}    indicatorcolors indcolcnfg=LCDdark); {\sf       // colors of screen and data}
}

The format parameter is the string analogous to that used in the
standard printf function. The frame parameter is reasonable to change
to FRAMED when you use POPUP or PERM type of Indicator, and leave
UNFRAMED when you use FIXED type, because FIXED type Indicator is
usually embedded in the board or panel. You have to keep in mind that
changing the default data font will slow down the overall performance,
because displaying the vector fonts takes excessive time. The
indcolcnfg defines the color scheme. There are four pre-defined color
schemes for Indicator:\\
 LEDind    - red light-emitting diodes,\\
 LUMind    - green cathode-ray display,\\
 LCDdark   - liquid crystal display,\\
 LCDbright - back-lit liquid crystal display.\\\\
Example:\\

{\footnotesize\begin{verbatim}
Indicator<float> *pindTemp = new Indicator<float>
      (0,0,FIXED,"Temperature",
       10,                     // width of disp. in chars
       &Temp,"%.2f K",         // variable and format, temperature in Kelvin
       UNFRAMED,procDummy,     // no paint proc. defined
       0,1,                    // font and size of number
       SMALL_FONT,4);          // font and size of title
\end{verbatim}}

Unframed indicator pindTemp is initialized at the left top corner of
the screen. Later in the program, when the true location of pindTemp
will be calculated, you can use MovetoXY method, inherited from the
object base class, to relocate pindTemp before painting.

If you don't want to attach any variable to the indicator you can use
class \_Indicator (it is not a template class). Then in the constructor
you must omit the parameter variable and you cannot use Refresh
method.\\\\
{\large Data members:}\\

All are inherited from the object base class (sect.4).\\\\
{\large Methods:}\\

Includes methods inherited from the object base class (sect.4).\\

{\bf\raggedright
 void cls();}

Clears display. Inherited from display  class.\\

{\bf\raggedright
 virtual void Paint(void);}

Paints the indicator and clears its display.\\

{\bf\raggedright
 void Refresh(void);}

Clears the display and puts the value of the attached variable in
accordance
with the format defined in the constructor.\\

{\bf\raggedright
 void Put(...);}

Puts data on the display in accordance with the format defined in
the constructor. You may consider it is as pritnf( format, ...).\\\\
Example:\\
{\footnotesize\begin{verbatim}
\hspace{2cm} pindTemp->Put( 77.2);
or
\hspace{2cm} Temp=77.2;  pindTemp->Refresh();
\end{verbatim}}
Here pindTemp is declared in the preceding example. After the execution of
one of these fragments the indicator will display:
 "    77.2 K".\\

{\bf\raggedright
 void Puts(char *str);}

Puts string str on the indicator. This method doesn't use format. So
you can display on the indicator any message that fits the width of
indicator.\\\\
Example:

{\footnotesize\begin{verbatim}
   pindTemp->Puts( "Overflow");
\end{verbatim}}
{\large Color schemes:}\\

Color pattern for Indicator is provided by the structure:\\

{\raggedright
 struct indicatorcolors\{ COLORS\\
\hspace{4cm}                      title,\hspace{1cm}// color of title\\
\hspace{4cm}                      foregr,\hspace{1cm}// foreground color\\
\hspace{4cm}                      backgr;\hspace{1cm}// background color}\};\\

There are four pre-defined color schemes for Indicator:\\
 LEDind, LUMind, LCDdark, LCDbright.

\subsection*{4.3 Graph}

Graph allows you to display data graphically. It is a
very versatile type of Objects and its usage highly depends on the
imagination of the programmer. Graph class methods allow to put on the
display lines or dots, draw arrays or math functions as curves or
histograms in both linear or logarithmic scales or mixed.\\

 * Type parameters XType and YType. Here we have used the new feature
 of C++ - class templates. Class Graph is in effect a template. Type
 parameters XType and YType are for type of values on the x-and y-axes.
 They can take the next values: double, float, long, int, unsigned
 long, unsigned int, char, unsigned char. When declaring the instance
 of Graph you have to define the types of axes.\\\\
Example:
{\footnotesize\begin{verbatim}
   Graph<int,double>  grFourier( ..... );
\end{verbatim}}

It means that you can display on the grFourier array of double values
over integer parameter or double function with integer parameter.\\\\
Constructor:\\
{\bf\raggedright
 Graph (    {\sf // ---- ALL SIZES IN VGA PIXELS ------}\\
\hspace{1.2cm}  int x0,int y0,         {\sf     // where to paint graph}\\
\hspace{1.2cm}  objtype type,          {\sf     // may be FIXED, PERM, POPUP}\\
\hspace{1.2cm}  char * title,          {\sf  // title of graph}\\
\hspace{1.2cm}  int xtics,int ytics,   {\sf     // number of tic marks}\\
\hspace{1.2cm}  int xpixtic,int ypixtic,{\sf // number of pixels between tics}\\
\hspace{1.2cm}  float xval0,float yval0,{\sf  // values of x,y (LIN) or powers of 10 (LOG) at origin}\\
\hspace{1.2cm}  float xticinc,float yticinc,{\sf // increment of tick labels only for LIN scales}\\
\hspace{4cm}           {\sf     //------------ Hereafter are defaults -------}\\
\hspace{2cm}     {\sf  // procedure supplied by programmer to repaint Graph}\\
\hspace{1.2cm}  void (far *paintproc)()=procNULL,\\
\hspace{1.2cm}  char * xtitle = "",char * ytitle = "",{\sf // axes titles}\\
\hspace{2cm}     {\sf  // format of tic labels. ! Can be only float \%[..]f !}\\
\hspace{1.2cm}  char * xticfmt = "",char * yticfmt = "",\\
\hspace{1.2cm}  int xscale=LIN, int yscale=LIN,{\sf // type of scale, may be LIN or LOG}\\
\hspace{1.2cm}  int frame=FRAMED,        {\sf // display may FRAMED or UNFRAMED}\\
\hspace{4cm}                                   {\sf     // fonts for}\\
\hspace{1.2cm}  int titlefont=0,int titlefontsize=1,   {\sf     // title}\\
\hspace{1.2cm}  int axtitlefont=0,int axtitlefontsize=1,{\sf //  axes titles}\\
\hspace{1.2cm}  int ticfont=SMALL\_FONT,int ticfontsize=2,{\sf // tic labels}\\
\hspace{4cm}                                   {\sf     // color schemes for}\\
\hspace{1.2cm}  graphcolors graphcolconfig=YellowOnCyan,  {\sf  // display}\\
\hspace{1.2cm}  plaquecolors framecolconfig=plaquecoldflt, {\sf // frame}\\
\hspace{1.2cm}  int gridstyle=0x5555);          {\sf // style of grid lines}
}

Creates Graph with specified parameters. Number of tic marks on the
axes is defined by parameters xtics and ytics. The distance between tic
marks in VGA pixels is controlled by xpixtic and ypixtic.
The type of scale of x or y axes may be of two kinds - linear (LIN) or
logarithmic (LOG). In other words we say that x or y axes are in LIN or
LOG mode. These modes are set by parameters xscale and yscale when calling
the constructor and cannot be changed later. For linear scale you can
define the difference between neighbouring tic labels, we call it tic
label increment, by xticinc or yticinc parameters. For logarithmic
scales these parameters are senseless because the difference in this
case is pre-defined as a power 1 of 10, so xticinc or yticinc can take
any value.

If the axis is in LIN mode, then the value of displayed data at the
origin of graph ( the origin is the LEFT-BOTTOM corner of Graph's
display ) is defined by xval0 or yval0 as a float point number. If the
scale is logarithmic, then these parameters define the power of 10 at
the origin. It may be a positive or negative integer.
The xtitle and ytitle parameters supply the titles alongside the
axes. The font for these titles is defined by axtitlefont and
axtitlefontsize. You can also customize the font style for tic labels
redefining parameters ticfont and ticfontsize.
Style of grid lines also may be customized by programmer. The gridstyle
parameter provides the bit pattern for grid lines.\\
Example:

{\footnotesize\begin{verbatim}
Graph<int,float>
 grFourier( 0, 0, FIXED, "Fourier transform",   // title
            24, 18,      // number of tic marks
            20, 20,      // number of pixels between tics
            0, min_y,    // values of x,y at origin
            (NumPoints+1)/24., (max_y-min_y)/18.,// increment of tick labels
            procDummy,         // no paint procedure
            "Frequency","Amplitude",// axes titles
            "%.0f","%.1f");    // format of tic labels
\end{verbatim}}

{\large Data members:}\\

All are inherited from the object base class (sect.4).\\\\
{\large Methods:}\\

Includes methods inherited from the object base class (sect.4).\\

{\bf\raggedright
 virtual void Paint(void);}

Paints Graph Object with empty display.\\

{\bf\raggedright
 virtual void cls();}

Clears the display (we also call it paper), removing all lines, curves and
etc. and repainting the grid.\\

{\bf\raggedright
 void DrawGrid(void);}

Repaints the grid lines.\\

{\bf\raggedright
 void SetInk( COLORS inkcolor);}

Sets default color of ink. It is a color used to draw dots, lines,
curves, fill rectangles on the graph, when the color parameter is not
specified for the drawing method.\\

 * The color parameter. In the following methods color=-1 means that if
 you omit color parameter default ink color will be used. If you don't
 omit color parameter then you can specify any of BGI colors.\\

        //--- DOT\\

{\bf\raggedright
 void PutDot( double x, double y, int color=-1 );}

Paints a single pixel on the paper of graph. The x and y are the
co-ordinates of pixel and must be defined in units of x and y axes.\\
Example:

{\footnotesize\begin{verbatim}
 for ( i=0; i<NumPoints; i++)
    grFourier.PutDot( i, y[i], YELLOW);
\end{verbatim}}

        //--- LINE\\

{\bf\raggedright
 void PutLine( double x0, double y0,\\
\hspace{6cm}           double x1, double y1, int color=-1 );}

Paints the line on the paper of graph. The line connects points (x0,y0)
and
(x1,y1) defined in units of x- and y- axes.\\
Example:

{\footnotesize\begin{verbatim}
 for ( i=0; i<NumPoints-1; i++)
    grFourier.PutLine( i, y[i], i+1, y[i+1] );
\end{verbatim}}

        //--- FUNCTION\\

 ** Note that the function cannot have negative values if y-axis was
set to LOG mode.\\

{\bf\raggedright
 void ShowCurve( int numpoints, YType (far *func)(XType), int color=-1 );}

Draws math function func with one parameter as a curve. The numpoints
defines the number of samples. More samples means smoother curve and
longer time of drawing. Function is scanned equidistantly from the
origin of x-axis to its end.\\

{\bf\raggedright
 void HideCurve( int numpoints, YType (far *func)(XType) );}

Is opposite to ShowCurve - clears out the curve from paper
and redraws the grid.\\

        //--- ARRAY\\

  ** Note that array elements cannot have negative values if y-axis was
  set to LOG mode.\\

{\bf\raggedright
 void ShowCurve( int numpoints, XType x0i, XType xmaxi,\\
\hspace{6cm}            YType far * array, int color=-1);}

Shows array as a curve on the graph. The numpoints is the number of
elements of array. The x0i and xmaxi are values on the x-axis
associated with correspondingly first and last elements of array. The
elements of array are drawn equidistantly along x-axis. Parts of the
curve lying behind Graph's display are cut out.\\
Example:\\
\hspace{1cm}  grFourier.ShowCurve( NumPoints, 0, NumPoints-1, y, YELLOW);\\\\

{\bf\raggedright
 void HideCurve(int numpoints, XType x0c, XType xmaxc,\\
\hspace{6cm}                   YType far * array );}

Is opposite to ShowCurve - clears out the curve from paper
and redraws the grid.\\

{\bf\raggedright
 void ShowHistogram( int numpoints, XType x0i, XType xstep,\\
\hspace{6cm}                YType far * array, int color=-1 );}\\

  ** If x-axis has been set to LOG mode, calling ShowHistogram
method interrupts the program with the error message:\\
  {\it Graph::ShowHistogram : X-scale cannot be LOG for histogram}\\

Shows array as a histogram. The numpoints is the number of elements of
array. The x0i is the value on the x-axis associated with the first
element of array. The distance between neighbouring bars of histogram
is defined by xstep parameter (in the unit of x-axis). The width of bar is
calculated automatically.\\
Example:

  grFourier.ShowHistogram( NumPoints, 0, 1023 , y );\\

{\bf\raggedright
 void HideHistogram( int numpoints, XType x0a, XType xstep,\\
\hspace{6cm}                YType far * array, int color=-1 );}

Is opposite to ShowHistogram - clears out the histogram
from the paper and redraws the grid.\\

        //--- TWO ARRAYS\\

  ** Note that array elements cannot have negative values if axis was
  set to LOG mode.\\

{\bf\raggedright
 void ShowCurve(int numpoints, XType far *Xdata,\\
\hspace{6cm}                  YType far *Ydata, int color);}

Arrays must have equal number of elements. Xdata and Ydata arrays
provide coordinates of points of the curve on the graph. The numpoints
is the number of elements of arrays. Parts of the curve lying behind
Graph's display are cut out.\\

{\bf\raggedright
 void HideCurve(int numpoints, XType far *Xdata,\\
\hspace{6cm}                     YType far *Ydata);}

Is opposite to ShowCurve - clears out the curve from the paper
and redraws the grid.\\\\
{\large Color schemes:}\\

There are four pre-defined color patterns for Graph:\\

{\footnotesize\begin{verbatim}
struct graphcolors            // Graph color structure
{ COLORS
   Paper,      Ink, Grid,      Title, AxesTitles, TicLabels ;};
const graphcolors
WhiteOnCyan =
  { CYAN,    WHITE, LIGHTCYAN, RED, BLACK,         BLUE },
YellowOnCyan =
  { CYAN,     YELLOW, LIGHTCYAN, RED, BLACK,       BLUE };
GreenOnBlue =
  { BLUE, LIGHTGREEN, LIGHTBLUE, RED, BLACK,       BLUE },
YellowOnBlue =
  { BLUE,     YELLOW, LIGHTBLUE, RED, BLACK,       BLUE };}
\end{verbatim}}


\subsection*{4.4 Board}

You can consider Board as a plaque that has the generic features of
the object. Indeed the Board class is derived from the plaque and object
base classes. The main destination of Board Objects is to provide
panels for forming more complicated constructions, consisting of
Indicators, buttons, Graphs and so on. This allows to manipulate the whole
construction as an integral object.\\\\
Constructor:\\

{\bf\raggedright
 Board(\\
\hspace{1cm}    int x0,int y0,  {\sf // coord. of LEFT-TOP corner of Board}\\
\hspace{1cm}    objtype type,          {\sf     // may be FIXED, PERM, POPUP}\\
\hspace{1cm}    char * title,          {\sf     // title of Board}\\
\hspace{1cm}    int xlength,int ylength,{\sf // size of board}\\
\hspace{5cm}                            {\sf //---------- Hereafter are defaults}\\
\hspace{3cm}           {\sf     // proc supplied by programmer to repaint Board,}\\
\hspace{1cm}    void (far * paintproc)()=procNULL,{\sf // only for PERM indicators}\\
\hspace{1cm}    int  titlefont=0,int titlefontsize=1,{\sf    // font for title}\\
\hspace{1cm}    COLORS titlecolor=RED,               {\sf    // color of title}\\
\hspace{1cm}    plaquecolors brdcolcnfg=plaquecoldflt);{\sf  //colors of Board}
}

All parameters here are familiar except xlength and ylength. These
parameters define the size of Board in VGA pixels. Sizes of other
Objects are calculated by {\it Virtual Panels} automatically and depend
on types and
sizes of fonts, formats and so on. The advantage of the direct size
definition is that the real size of Object in this case doesn't depend
on the aspect ratio of current graphics mode. You can set xlength and
ylength zero if you don't know at the moment the size of the Board, and
set it later using method ChangeSize.\\\\
{\large Data members:}\\

Includes data members inherited from the object base class (sect.4).\\

{\bf\raggedright
int y0p;}

The upper y location above which area occupied by Board's title starts.
Can be used for disposing Objects on the Board. See example below.\\\\
{\large Methods:}\\

Includes methods inherited from the object base class (sect.4).\\

{\bf\raggedright
 virtual void Paint(void);}

Paints Board.\\

{\bf\raggedright
 void ChangeSize( int xlength, int ylength);}

You can set vertical and horizontal lengths of Board zero if you don't
know at the moment the size of the Board, and change them later using
this method. Such situation occurs because {\it Virtual Panels} automatically
calculates sizes of other Objects. You cannot know in advance the
required size of the Board, when the Objects to be put on the Board,
are declared after the Board. In the following example the Board
\_Hysteresis represents the panel with indicators and button system.
The panel \_Hysteresis is declared in the main function, while
indicators and buttons are declared separately in button procedure.
Of course
\_Hysteresis could also be declared in that procedure, but then it would
be inaccessible to the main Loop function in the main function and you
could not , for example, drag it on the screen. To be accessible to the
Loop function the Object must be
declared before that function.\\
Example 4.4.1:

{\footnotesize\begin{verbatim}
#include <vphead.h>     // must be included first
#pragma hdrstop         // stop precompiling headers

#include <vpbase.h>     // Virtual Panels header files
#include <vpboard.h>
#include <vpindic.h>
#include <vpbutt.h>

#include "rt.h"         // users definitions

// Global pointers.
// Are necessary for an access to Objects from button procedures
Board *pbdHysteresis;   // panel declared in main()
Indicator<int> *pindAC, *pindLimDC;// indicators declared in bpHyst()

void far bpHyst(void)   // button procedure declaration

main
{InitAndCopyright("* Board example *" );
 butsystem bsMain( MASTER ); //install Main button system
 .
 .
           //----------- HYSTERESIS PANEL ------
Board bdHysteresis(x0s,y0s,POPUP,"Hysteresis measurement",
                  0,0,bpHyst );// size of board is while zero

pbdHysteresis=&bdHysteresis;    // global pointer
 .
 .
           //---------- MAIN BUTTON SYSTEM -----
 butgrp HorizButtons( 3, maxy-25, 70, 21, HORIZ, 2);
  button butQuit("Quit",'Q','q',bpQuit,0,1,quittexcol,quitbutcol);
  button butHyst( "hYster", 'Y','y', bpHyst);
 .
 .
 bsMain.Loop(MainBackgr); // main Loop
 bpQuit();                // quit application
}
//------------------------ HYST BUTTON PROCEDURE -------------------
//-- POPUP panel with two indicators and buttons associated with them.
//-- Indicators shows current values of parameters - value of AC
//-- current and limit of DC current. Pushing buttons calls button
//-- procedures that allow you to change current values of parameters.

void far bpHyst(void)
{
butsystem bsHyst;       // install new button system

int indy0 = pbdHysteresis->y0p; // TOP coord. of indicators

         //--------------- Indicators ------

Indicator<int>//-- x0 --- y0 - type - title - width - var - format --
 indAC( Hysteresis->x0, indy0, FIXED, "AC",       5, &altI, "%d"),
 indLimDC( _indAC.xmax, indy0, FIXED, "DC limit", 5, &limDC, "%d");

 pindAC1=&indAC1;  pindLimDC=&indLimDC; // global pointers

        //---------------- Buttons ------
#define SHIFT   10      // shift between buttons
int                     // length of button
 length = indLimDC.xmax - indLimDC.x0 - SHIFT;

butgrp gr( Hysteresis->x0 + SHIFT/2, _indAC1.ymax, length , 18,
                                                 HORIZ, SHIFT);
  button butAD1(      "AC", 'A','a', bpAC1,   SMALL_FONT, 4);
  button butLimDC( "Limit", 'L','l', bpLimDC, SMALL_FONT, 4);

       //-- Now all sizes have been calculated and we can
       //-- set the right size of the Hysteresis panel
       //-- and paint the panel with all details on it.
pbdHysteresis->ChangeSize(indLimDC.xmax - pbdHysteresis->x0,
                        indLimDC.ymax - pbdHysteresis->y0 + SHIFT);

       //---------------- Paint the whole board
pbdHysteresis->Paint(); // paint panel first
indAC.Paint();          // then indicators
indLimDC.Paint();
gr.Paint();             //      and buttons
              // After that display values of
indAC.Refresh();        //      AC current
indLimDC.Refresh();     //      limit of DC current

       //-- Here program enters into the new Virtual Panels Loop.
       //-- HystBackgr deals with measurements. Pushing buttons
       //-- on the panel you stop measurements and can change
       //-- parameters of system. You cannot leave the measurement
       //-- until measInProgress flag is set FALSE from HystBackgr.
do
 bsHyst.Loop(HystBackgr);
while(measInProgress);

 pbdHysteresis->Remove();  //  Remove Hysteresis panel from the screen,
 pbdHysteresis->MkActive();//  but put it on the top of Stack of Object
                           //  to be able to relocate it if necessary.
 object::RepaintScr();     //  Before leaving restore the screen.
}
\end{verbatim}}

This example is a simplified fragment of a real application. Besides
ChangeSize method it illustrates the use of many other Objects and
methods we have described till now. We recommend to read this fragment
carefully, paying attention to the comments, to understand the style of
programming {\it Virtual Panels} applications.


\subsection*{4.5 Output Text Box}

The Outbox class is derived from two base classes - display and object.
It is a kind of a text window for messages. Of course it is not a
fully-fledged text window. You hardly can use Outbox for editing files. But
it suits well for outputting text information for various purposes.
The more complete text window may be derived from Outbox and will be
included in the following versions of {\it Virtual Panels}.\\

 * Background mode. It is a mode supported by Outbox printing method. If
 the background mode is on then printing the new text over the old one
 will purge away the latter. If it is off (transparent mode) then the
new text will be
 printed over the old one without background. This mode works only if
 the current mode of text justification is LEFT\_TEXT. For other text
 justifications background mode is always off.\\\\
Constructor:\\

{\bf\raggedright
Outbox(\\
\hspace{1cm}    int x0, int y0, {\sf // coord. of LEFT-TOP corner of Indicator}\\
\hspace{1cm}    objtype type,   {\sf    // may be FIXED, PERM, POPUP}\\
\hspace{1cm}    char * title,   {\sf    // title of Outbox}\\
\hspace{1cm}    int colomns, int rows,{\sf      // size of box in characters}\\
\hspace{5cm}                   {\sf     //---------- Hereafter are defaults}\\
\hspace{1cm}    int frame = FRAMED, {\sf        // display may FRAMED or UNFRAMED}\\
\hspace{3cm}          {\sf      // procedure supplied by programmer to repaint Outbox}\\
\hspace{1cm}    void (far * paintproc)() = procNULL,\\
\hspace{7cm}                                             {\sf  //       font}\\
\hspace{1cm}    int  titlefont = 0, int titlefontsize = 1,{\sf // of title}\\
\hspace{1cm}    int  textfont = SMALL\_FONT, int textfontsize = 5,{\sf // of text}\\
\hspace{7cm}                                           {\sf     //    colors}\\
\hspace{1cm}    plaquecolors obxcolcnfg = plaquecoldflt,{\sf // of frame}\\
\hspace{1cm}    outboxcolors obxcolors = obxcoldflt,    {\sf // of display}\\
\hspace{1cm}    int titlejustify = CENTER\_TEXT);       {\sf // for system use}
}

Most of parameters of constructor are typical for Objects. About color
schemes see the corresponding subsection below.\\\\
{\large Data members:}\\

All are inherited from the object base class ( See sect. 4 ).\\\\
{\large Methods:}\\

Includes methods inherited from the object base class ( sect.4 )\\

{\bf\raggedright
 virtual void Paint(void);}

Paints Outbox clears display, and resets current printing position (it
will be at the LEFT-TOP corner of display). Text justification will be
LEFT\_TEXT.\\

{\bf\raggedright
 void SetTextJustify( text\_just xtextjust = LEFT\_TEXT);}

Justifies text in the x-direction and performs Line Feed (LF). The
xtextjust may be LEFT\_TEXT, CENTER\_TEXT or RIGHT\_TEXT.\\

{\bf\raggedright
 virtual void cls();}

Clears display, and resets the current printing position.\\

{\bf\raggedright
 void GotoXY( int column, int row);}

Moves the printing position to the {\it column} and {\it row}.
If {\it row} = -1 then the
printing position moves to the bottom of the display.\\

{\bf\raggedright
 void GetXY(int * column,int * row);}

Gets the current printing position.\\

{\bf\raggedright
 void SetTextColor( COLORS newcolor);}

Changes current text foreground color to the newcolor.\\

{\bf\raggedright
 void SetHLTextColor(COLORS newHighLightcolor);}

Changes current highlight text color to the newHighLightcolor.\\

{\bf\raggedright
 void YesBkgnd(void);\\
 void NoBkgnd(void);}

Switches background mode on or off.\\

{\bf\raggedright
 void Put(  char *text, int highlight = OFF);\\
 void Putn( char *text, int highlight = OFF);}

Prints a string. String is highlighted if highlight = ON. Putn also
performs carriage return.\\

{\bf\raggedright
 int  Printf(  int hilight, const char *format, ...);\\
 int  Printfn( int hilight, const char *format, ...);}

Send formatted output to Outbox. Behave exactly like printf, except
for they don't accept control characters. Text is highlighted if highlight
= ON. Printfn also performs carriage return.\\\\
{\large Color schemes:}\\

{\raggedright
Color pattern for the Outbox class is provided by the structure:

{\footnotesize\begin{verbatim}
struct outboxcolors { COLORS
                        title,
                        text,
                        hltext, // highlighted text
                        paper; };
 \end{verbatim}}

Default color scheme is:

{\footnotesize\begin{verbatim}
const outboxcolors obxcoldflt =
                   { RED, WHITE, YELLOW, LIGHTGRAY };
                // title   text  hltext      paper
 \end{verbatim}}

For Error Message Box you can use a color scheme defined in the header
file:

{\footnotesize\begin{verbatim}
const plaquecolors  errboxcolors = { RED, RED, LIGHTRED };
const outboxcolors  errcolors = { WHITE, WHITE, YELLOW, RED };
 \end{verbatim}}

Example:\\
See Example 3.1.2, where the use of the Outbox and its methods is
illustrated.}


\subsection*{4.6 Input Text Box}

The Inbox class is derived from the Outbox class described in the
preceding section. It may be considered as a single row Outbox Object
with the new added feature -  Scanf method. Indeed Inbox is
a {\it Virtual Panels} style scanf.\\\\
Constructor:\\

{\bf\raggedright
Inbox (\\
\hspace{1cm}    int x0,int y0,  {\sf // coord. of LEFT-TOP corner of Indicator}\\
\hspace{1cm}    objtype type,   {\sf // may be FIXED, PERM, POPUP}\\
\hspace{1cm}    char * title,   {\sf // title of Inbox}\\
\hspace{1cm}    int columns,    {\sf // size of box in characters}\\
\hspace{5cm}                    {\sf //---------- Hereafter are defaults}\\
\hspace{1cm}    int frame=FRAMED,{\sf   // display may FRAMED or UNFRAMED}\\
\hspace{7cm}           {\sf     // procedure supplied by programmer to repaint Inbox}\\
\hspace{1cm}    void (far * paintproc)()=procNULL,\\
\hspace{1cm}    int  titlefont=0,int titlefontsize=1,   {\sf // title font}\\
\hspace{1cm}    plaquecolors obxcolcnfg = plaquecoldflt,{\sf // colors of frame}\\
\hspace{1cm}    outboxcolors obxcolors  = obxcoldflt ,  {\sf //     and display}\\
\hspace{1cm}    int titlejustify = CENTER\_TEXT);       {\sf // for system use}
}

The constructor is like the Outbox constructor except the {\it row}
parameter
is absent (it always is equal to 1).\\\\
{\large Data members:}\\

All are inherited from the object base class (see sect.4).\\\\
{\large Methods:}\\

Includes all methods of Outbox (sect.4.5) and object (sect.4) classes.\\

{\bf\raggedright
 int Scanf( const char *format,...);}

Scans a series of input fields one character at a time, formats each
field according to the format specifier passed in the format string
*format and stores the formatted input at an addresses passed as an
arguments following *format. In effect it is the same standard scanf
function suited for the {\it Virtual Panels}. To enter data push the one
of the next keys on the keyboard: Enter, ESC, Tab or Shift-Tab.\\
{\raggedright
Returns:\\
\hspace{2.2cm}     0 if Shift-Tab has been pushed\\
\hspace{2.2cm}     9 if Tab has been pushed\\
\hspace{2cm}    13 if CR has been pushed\\
\hspace{2cm}    27 if ESC has been pushed\\
\hspace{2cm}    -1 if no data has been entered (error)}\\\\
{\large Color schemes:}\\

{\raggedright
The default color scheme for Inbox is

 {\footnotesize\begin{verbatim}
const outboxcolors ibxcoldflt=
        { YELLOW, WHITE, YELLOW, LIGHTGRAY };
//         title   text  hltext      paper
 \end{verbatim}}

Example:

 {\footnotesize\begin{verbatim}
 char resp;
 Inbox *ibxConfirm new Inbox( maxx>>2, maxy>>2, POPUP, "Measurement Ended", 25);
   ibxConfirm->Paint();
   ibxConfirm->cls();
   ibxConfirm->Put( "Save data file (N) ? : ", 1);
   ibxConfirm->Scanf( "%c", &resp);
   if ( resp=='N' || resp=='n' )
      unlink(nameTdepDat);
   ibxConfirm->Remove();
 \end{verbatim}}
}

\subsection*{4.7 Tabstop Input Box}

It is a tabstop version of the Inbox Object. The TSInbox class is a
template class derived from both tabstop and Inbox classes. Use of it
simplifies programming compared with the Inbox Object. You must only
declare TSInbox instance before the Loop function and it will be
included into the current button system and will be automatically
driven by the button system. No further calls are needed.
Automatically TSInbox instance deals only with the one variable
declared in constructor. The template parameter is the type of that
variable. You can write a processing procedure and attach it to the
TSInbox Object. In case of successful input the value of the variable
is transferred to this procedure which can process it and must return
the new value of the variable which is stored as an ultimate value.

Note that you can call Scanf method inherited from the Inbox class
if you want to scan other variables. TSInbox is FIXED and UNFRAMED.
This features cannot be changed.\\\\
Constructor:\\

{\bf\raggedright
TSInbox(\\
\hspace{1cm}    int x0,int y0,  {\sf // coord. of LEFT-TOP corner of Indicator}\\
\hspace{1cm}    char * title,   {\sf // title of Inbox}\\
\hspace{1cm}    int columns,    {\sf // size of box in characters}\\
\hspace{1cm}    T * variable,   {\sf // variable and its formats}\\
\hspace{1cm}    char * scanfmt, {\sf //  for scanning the new value}\\
\hspace{1cm}    char * printfmt,{\sf //  and printing the current value}\\
\hspace{5cm}                    {\sf    //---------- Hereafter are defaults}\\
\hspace{1cm}    T (far *proc)(T) = NULL,{\sf  // variable processing procedure,}\\
\hspace{1cm}    int titlefont=SMALL\_FONT,int titlefontsize=4,{\sf // title font}\\
\hspace{1cm}    plaquecolors obxcolcnfg=plaquecoldflt,{\sf // colors of frame}\\
\hspace{1cm}    outboxcolors ibxcolors=ibxcoldflt);  {\sf //     and display}
}

Here T is a template parameter. If the pointer to the processing
procedure is NULL then no call is made. The processing procedure must
be far and return the new value of the inputed variable.\\\\
{\large Data members:}\\

All are inherited from the object base class ( see sect. 4 ).\\\\
{\large Methods:}\\

Includes all methods of Inbox (sect.4.6), Outbox (sect.4.5) and object
(sect.4) classes. The Paint method is inherited from the Inbox class.\\

{\bf\raggedright
 void Refresh(void);}

Clears display and prints the current value of variable.\\

{\bf\raggedright
 virtual void Activate(void);}

Makes the TSInbox Object the active tabstop object in the current
button system. Then the current value of the variable is highlighted.
This can be done from console striking Tab or Shift-Tab keys one or
several times.\\\\
Example:\\

 {\footnotesize\begin{verbatim}
butsystem bsDlg;         // Declare the button system
 TSInbox<float>
   tibVol( 0, 0, "Volume (sm):", 12, &Vol, "%f", "%.2f");

 TSInbox<float>
   tibK2( 0 , tibVol.ymax, "Formation factor:", 12, &K2, "%f", "%.2f");

 butgrp grp1( (tibVol.xmax-tibVol.x0)/2 , tibK2.ymax+30 , 70, 21, VERT, 2);
  button butNorm( "Norm", 'n','N', bpNorm);
  button butHelp( "Help", 'h','H', bpHelp);
  button butQuit( "Quit", 'q','Q', bpQuit, 0,1,quittexcol,quitbutcol);

         // Paint the button system
 tibVol.Paint();
 tibK2.Paint();
 tibVol.Refresh();
 tibK2.Refresh();
 grp1.Paint();

         // Turn on the button system
 bsDlg.NextButton();
 bsDlg.Loop(procDummy);
 \end{verbatim}}


\section*{5. Writing {\it Virtual Panels} applications}

\subsection*{5.1. Style of programming}

The C language is simple and handy, what makes it extremely popular
among programmers. {\it Virtual Panels} is written in the manner that takes the best
of both languages. I tried to use C++ features only when they were
actually more suitable. Otherwise I adhered to the C language. I have
used, for example, instead of C++ style streams C style streams, which
seem to be more handy in use.

Program  is recommended to be divided into several modules. In one must
be the main function and global variables. The other modules may be
devoted to the paint and button procedures, menu procedures. The menu
system is declared in the stand-alone menu system function that is then
registered in the main function or button procedure before the Loop
function call. You can define you own dialogue boxes and other objects
in your original style using powerful inheritance method of C++.
{\it Virtual Panels} gives only basics for data presentation, at least
in this version.

\subsection*{5.2 Header files}

You must include the {\it Virtual Panels} header files in your modules. The top of
your module may look so:

{\footnotesize\begin{verbatim}
#include <vphead.h>     // must be included first, contains
#pragma hdrstop         // all necessary standard headers

#include <vpbase.h>      // contains basics of Virtual Panels
                         // Must be included in any case
// These headers are optional. You must include them if you use:
#include <vpbutt.h>     // the button    system
#include <vpmenu.h>     // the menu      system
#include <vpled.h>      // the LED       class
#include <vpboard.h>    // the Board     class
#include <vpoutbox.h>   // the Outbox    class
#include <vpinbox.h>    // the Inbox or TSInbox  class
#include <vpindic.h>    // the Indicator class
#include <vpgraph.h>    // the Graph     class
 \end{verbatim}}

\subsection*{5.3. Global pointers to Objects}

The next section of module is a declaration of global pointers. It may
look like that:

{\footnotesize\begin{verbatim}
Indicator<float> *pindMinT,*pindMaxT;
Indicator<int> *pindStep,*pindN;
extern Indicator<float> *pindDisbal,*pindModule;
extern Board *pbdTdependance;
 \end{verbatim}}

The global pointers are necessary for other functions or modules to
have access to the Objects declared in the main function and button
procedures. In practice almost all Objects require global pointer.
Look at the Example 4.4.1.

\subsection*{5.4 Custom color schemes}

Sometimes you would like to customize colors of Objects or Controls. In
these case it may be the next section of program. Of course, it is
better to do this in the header file.

\subsection*{5.5. Background Procedure}

Background Procedure is a procedure which will be executed while
{\it Virtual Panels}
is polling console. You can provide Background Procedure for each
button or menu system when you activate the button or menu system by
function calls bsMain.Loop(MainBackgr) or msMain.Loop(MainBackgr).\\\\
The Background Procedure may be as simple as that:

{\footnotesize\begin{verbatim}
void far MainBackgr(void)
{
struct  time t;
static int sec,hund;
       // here is realized delay
 gettime(&t);
 if (sec==t.ti_sec)
   if ((t.ti_hund-hund)< 50)
     return;

     // A1 and B1 are mail boxes updated by ISR in real time
 a1 = adc2volt( A1 - ADC_ZERO );
 b1 = adc2volt( B1 - ADC_ZERO );
 Temperature = MeasureTemperature();
     // update indicators on the screen
 pindTemperature->Refresh();
 pindInphase->Refresh();
 pindOutphase->Refresh();

 sec=t.ti_sec; hund=t.ti_hund;  // for delay
 if (errCodeISR) errExit();     // exit if interrupt routine failed
}
 \end{verbatim}}

The more complicated Background Procedure will consist of several
phases. General structure of such Background Procedure may look as
follows:

 {\footnotesize\begin{verbatim}
void far TdepBackgr(void)
{
// The code common for all phases
 .
 .
 measureA1B1T();
 updateIndicators();

 switch ( phase )
 {
  case 0:       //--- Initialization phase
       // Here the Temperature Dependence measurement
       // procedure is initialized.
       .
       .
       measInProgress=1;
       phase = 1;       // next is the phase 1
       break;
  case 1:       //--- Measurement phase
       if ( (Temperature > maxT) || (Temperature < minT) )
        phase = 10; // end measurement if temperature is out of range
       else
          { // Here measurement are going
           .
           }
       break;
  case 10:      //--- Stop measurement
       .
       .
       measInProgress=0;
       phase = 11;      // switch backgr measurement in idle mode
       fclose(dat);     // save data file if necessary
       if ( !Confirm(" Save data file ? ") )
           unlink( nameTdepDat);
       break;
  case 11:;     //--- Measurement is idle
 }//-- switch
}//------ TdepBackgr(void)
 \end{verbatim}}

\subsection*{5.6. Main Module}

It is the module that contains the main() function. First must go
header files (sect.5.2). Then if you have not included object code of
EGAVGA.BGI into your project or GRAPHICS.LIB, include the line:

{\footnotesize\begin{verbatim}
 int far EGAVGA_driver_far[1];
  \end{verbatim}}

Next goes the  declarations of global pointers (sect.5.3).\\
After that you would like to write the Background Procedure.\\\\
The main function starts with the initialization of {\it Virtual Panels}:

  {\footnotesize\begin{verbatim}
main()
{
InitAndCopyright("Copyright (c) O.Rasizade, 1992");
butsystem bsMain(MASTER); // bsMain button system is the master
                          // of Dragging area
// Next go declarations of Objects to be controlled by bsMain
button
// system. The object may be declared by two ways. One way
is to
// allocate the Object in the stack declaring:

Indicator<float>
  indTemperature        //-- TEMPERATURE INDICATOR
       ( 0, 0, PERM, "Temperature", 10, &Temp,"%.2fK");
   // here the global pointer is initialized
pindTemperature = &indTemperature;

// The other way is to allocate the Object in the heap:
pindTemperature = new Indicator<float>
                  ( 0, 0, PERM, "Temperature",10, &Temp,"%.2fK");
// In this case don't forget to delete the instanse:
// delete pindTemperature;

// After declarations of Objects it is reasonable to declare
// button groups:
butgrp HorizButtons(3,maxy-25,70,21,HORIZ,2);
 button butQuit("Quit",'Q','q',bpQuit,0,1,quittexcol,quitbutcol);
 button butHelp("Help",'h','H',bpHelp);
 .
 .
 button butTdep("T-dep",'T','t',bpTdep);
 button butTdepGraph("gRaph",'R','r',bpTdepGraph);

// Now paint panels, FIXED Objects and buttons:
 .
 .
 HorizButtons.Paint();

// At last is the program itself:
                //---------- PROGRAM ---------
 InitCamac();   // initialization procedures
 InitLabTask();
 camEnInt();
 .
 .
 object::LoadCnfg(CNF_NAME);   // restore configuration
 object::RepaintScr();  // and paint PERM Objects as they
                        // were disposed in the last session
 bsMain.NextButton();   // light on the first button
 bsMain.Loop(MainBackgr);// activate main button system

 object::SaveCnfg(CNF_NAME);   // save configuration
 QuitVirtualPanels();
}// end of main()
 \end{verbatim}}

Note that the best way is to define starting coordinates of PERM and
POPUP Objects in the upper left corner of the Dragging area. If you
define them otherwise there is the chance that the disposition of the
PERM and POPUP Objects well suited for the the VGA high resolution mode
will ruin the screen when used in the EGA mode. That is because the
difference in sizes of fonts is not compensated. So it is a good
idea to dispose Objects from console what may be then saved by the
object::SaveCnfg function.


\subsection*{5.7. Button system in the button procedure}

Here is an example of a POPUP panel with its own button system:

 {\footnotesize\begin{verbatim}
//--- Button procedure: Temperature Dependence
void far bpTdep(void)
{
 .
 .
 phase = 11;    // No measurement - idle backgr. proc
butsystem bsTdep; // new button system is declared

// Here go declarations of Objects on the TDep panel
 .
 .
        //---------------- Buttons ------
butgrp gr1( .., .., .., 20);
// bpStartTdep sets phase=1 to start the measurement
  button butStart("Start measurement",'S','s',bpStartTdep,SMALL_FONT,4);
// bpStopTdep sets phase=10 to stop the measurement
  button butStop("stoP measurement",'P','p',bpStopTdep,SMALL_FONT,4);

// pbdTdependence panel (Board class) is declared in the main()
// with zero size. Set now its real size:
 pbdTdependence->ChangeSize(axmax-ax0,butStop.ymax-ay0);

//--- Paint whole panel
 pbdTdependence->Paint();
 .
 .
 gr1.Paint();

 bsTdep.NextButton();   // light on button
 do // about TdepBackgr look at sect. 5.5
  bsTdep.Loop(TdepBackgr);
 while(measInProgress);

 pbdTdependence->Remove();   // remove POPUP panel from the screen
 pbdTdependence->MkActive(); // now you can drag the panel from the
                             // Main Loop
}
 \end{verbatim}}

\subsection*{Appendix A. Error messages.}

{\it\raggedright
procNULL : Illegal object proc call}

  Improper call of the user-defined procedure was made. For example no
  paint procedure was defined for PERM Object.\\

{\it\raggedright
object::Save: Not enough far heap memory}

  There is not enough heap memory for saving underlying images.\\

  {\it\raggedright
Graph::ShowHistogram : X-scale cannot be LOG for histogram}

  If x-axis was set to LOG mode, program interrupts when
  calling ShowHistogram.\\


\subsection*{Appendix B. Objects control from keyboard}

{\normalsize\begin{verbatim}
Alt-F3          remove the active PERM Object from the screen
Ctrl-F5         start dragging the active PERM Object on the screen
Left, Right, Up, Down Arrows
                quick drag of the active PERM Object
Ctrl-Left, -Right, -Up, -Down Arrows
                slow but precise drag of the active PERM Object
Tab             go to the next button group or tabstop Object
Shift-Tab       go to the previous button group or tabstop Object
F6              make the next PERM Object active and repaint it
Alt             activate the menu system
Esc             exit from the button system
\end{verbatim}}
\vskip5cm
\begin{center}
{Рукопись поступила в издательский отдел\\
20 октября 1993 года}
\end{center}
\end{document}
